/*
 * 文件名：Jsons.java
 * 版权：MoonBox 
 * 修改人：Peter
 * 修改时间：2018年10月10日
 * 修改内容：新增
 */
package com.renzhebiao.lkang.utils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import com.alibaba.druid.util.StringUtils;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.core.util.DefaultIndenter;
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.renzhebiao.lkang.exception.ForbiddenException;

import lombok.extern.log4j.Log4j;

/**
 * JSON工具类
 * <p>
 * Jackson性能 测试请查看 https://github.com/eishay/jvm-serializers/wiki
 */
@Log4j
public class Jsons {

    /** 反序列化失败 */
    private static int          DESERIALIZE_FAILED = 500007;

    private static ObjectMapper objectMapper       = null;

    static {
        // 使用configure(value,boolean) 或者 enable/disable进行配置
        objectMapper = new ObjectMapper();
        // objectMapper.registerModule(new JaxbAnnotationModule()); 让jackson支持jaxb注解的配置
        // objectMapper.enable(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY); 属性排序
        // 为null的属性值不映射
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        // 允许使用非双引号属性名字
        objectMapper.enable(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES);
        objectMapper.enable(JsonParser.Feature.ALLOW_SINGLE_QUOTES);
        // 有属性不能映射的时候不报错
        objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        // 确定是否具有空值的map条目将被序列化,都带{}
        objectMapper.disable(SerializationFeature.WRITE_NULL_MAP_VALUES);

        // objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true) ;
    }

    public static void main(String[] args) {
        // Map<String, Object> a = new HashMap<String, Object>();
        // a.put("d", null);
        // System.out.println(toJson(a));
        // String a1 =
        // "{\"id\":\"1919,2299,2308,2310,2312,2313,2314,2315,2316,2317,2318,2319,2320,2322,2324,2336,2374\",\"deviceNo\":\"16116121101\",\"key\":\"2e345b610b93e2634ab09df415417a99fad44f6ef512,8fe06583c8bd8acfcc81d5\",\"wifiSN\":\"18V23F22K6\",\"time\":1461569910530,\"ip\":\"0:0:0:0:0:0:0:1\",\"imsi\":\"xx\",\"count\":\"1,2,3,2,1,3,1,2,3,2,1,3,1,2,3,2,1\",\"md5\":\"5f0de905842e580865449500b01a9826,2072118124b85e990d8a3d34414b2461,1ec8453fb7d1701a0dbd0b9c90e34a2d,0000fe5fd515861bcc87c50b32b7234a,1dfa927289e4ad9d67afb463d31e0cc3,331353ad93ae45b91935272945f09f55,b19a826ba1e1bc71931157c1f4d67654\",\"clientType\":2,\"installs\":0,\"shopId\":0,\"empId\":0,\"reqLog\":\"request-url:http://localhost:93/route/store/V1/up/app?wifiSN=18V23F22K6&imei=16116121101&count=1,2,3,2,1,3,1,2,3,2,1,3,1,2,3,2,1&imsi=xx&id=1919,2299,2308,2310,2312,2313,2314,2315,2316,2317,2318,2319,2320,2322,2324,2336,2374&md5=5f0de905842e580865449500b01a9826,2072118124b85e990d8a3d34414b2461,1ec8453fb7d1701a0dbd0b9c90e34a2d,0000fe5fd515861bcc87c50b32b7234a,1dfa927289e4ad9d67afb463d31e0cc3,331353ad93ae45b91935272945f09f55,b19a826ba1e1bc71931157c1f4d67654&key=2e345b610b93e2634ab09df415417a99fad44f6ef512,8fe06583c8bd8acfcc81d5,request-time:2016-04-25"+
        // "15:38:30.532,request-method:GET,UserAgent:Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML,
        // like"+
        // "Gecko) Chrome/48.0.2564.109 Safari/537.36\"}";
        //
        // System.out.println( getStr(a1, "id"));
    }

    public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }

    /**
     * 对象转JSON<br/>
     * 序列化对象
     * 
     * @param value
     * @return
     */
    public static String toJson(Object value) {
        if (value == null) {
            return null;
        }
        try {
            return objectMapper.writeValueAsString(value);
        } catch (IOException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    /**
     * 获取JSON字符串中的对应key的值
     * 
     * @param json json
     * @param key key
     * @return JSON字符串中的对应key的值
     */
    public static String getByKey(String json, String key) {
        String value = null;
        JsonNode rootNode = null;
        if (StringUtils.isEmpty(json)) {
            try {
                rootNode = objectMapper.readValue(json, JsonNode.class);
            } catch (IOException e) {
                log.error("Object to Json deserialize error", e);
                throw new ForbiddenException(DESERIALIZE_FAILED);
            }
        }
        if (null != rootNode) {
            if (rootNode.path(key).isArray() || rootNode.path(key).isContainerNode()) {
                value = rootNode.path(key).toString();
            } else if (rootNode.path(key).isValueNode()) {
                value = rootNode.path(key).textValue();
            }
        }
        if ("null".equalsIgnoreCase(value)) {
            value = null;
        }
        return value;
    }

    /**
     * 处理对象输出带换行空格格式的JSON字符串，记录日志。 { "code" : "", "desc" : "" }
     * 
     * @param o
     * @return
     */
    public static String stringify(Object o) {
        DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
        printer.indentArraysWith(new DefaultIndenter());
        try {
            return objectMapper.writer(printer).writeValueAsString(o);
        } catch (JsonProcessingException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    /**
     * JSON转对象<br/>
     * 反序列化对象
     * 
     * @param json
     * @param type
     * @return
     */
    public static <T> T toObj(String json, Class<T> type) {
        if (EmptyTools.isNull(json)) {
            return null;
        }
        try {
            return objectMapper.readValue(json, type);
        } catch (IOException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    /**
     * Json字符数组转Object
     * 
     * @param json
     * @param type
     * @return
     */
    public static <T> T toObj(byte[] json, Class<T> type) {
        if (EmptyTools.isNull(json)) {
            return null;
        }
        try {
            return objectMapper.readValue(json, type);
        } catch (IOException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    /**
     * Json字符串转化为list
     * 
     * @param <T>
     * @param json
     * @return
     * @throws IOException
     */
    public static <T> List<T> toList(String json, TypeReference<List<T>> typeReference) {
        if (EmptyTools.isNull(json)) {
            return null;
        }
        try {
            return objectMapper.readValue(json, typeReference);
        } catch (IOException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    /**
     * Json字符串转化为list
     * 
     * @param <T>
     * @param json
     * @return
     * @throws IOException
     */
    public static <T> List<T> toList(String json, Class<T> clazz) {
        if (EmptyTools.isNull(json)) {
            return null;
        }
        JavaType javaType = getCollectionType(ArrayList.class, clazz);
        try {
            return objectMapper.readValue(json, javaType);
        } catch (IOException e) {
            log.error("Object to Json deserialize error", e);
            throw new ForbiddenException(DESERIALIZE_FAILED);
        }
    }

    public static JavaType getCollectionType(Class<?> collectionClass, Class<?>... elementClasses) {
        return objectMapper.getTypeFactory().constructParametricType(collectionClass, elementClasses);
    }
}
